/**
 * 页面模态框
 * @file src\scripts\utils\modal.js
 * @author Verning Aulence
 * @date 2024-09-15 17:25:46
 * @description 需要搭配 modal.scss 使用，也可以根据 DOM 结构自定义样式
 **/

/**
 * 普通居中模态框
 * @param {Object} [params = {}]
 * @param {Element} [params.target] 模态挂载目标元素
 * @param {boolean} [params.hasMasklayer] 是否显示遮罩层
 * @param {boolean} [params.masklayerCanClose] 是否允许点击遮罩层关闭模态框
 * @param {string | Element} [params.title] 模态框标题
 * @param {string | Element} [params.content] 模态框消息内容
 * @param {boolean} [params.hasConfirmButton] 是否拥有确认操作按钮
 * @param {string} [params.confirmButtonText] 确认按钮文本
 * @param {'normal' | 'danger'} [params.confirmButtonType] 确认按钮类型
 * @param {Function} [params.closeCallback ] 关闭按钮回调函数
 * @param {Function} [params.confirmCallback ] 确认按钮回调函数
 * @description 关于默认值，可以查看方法参数的默认设置
 */
const normal = ({
  target,
  contentWidth,
  contentHeight,
  contentPadding,
  hasMasklayer,
  masklayerCanClose,
  title,
  content,
  hasConfirmButton,
  confirmButtonText,
  confirmButtonType,
  closeCallback,
  confirmCallback,
} = {}) => {
  // 创建类型为底部出现的模态框
  createModal({
    modalType: 'normal',
    target,
    contentWidth,
    contentHeight,
    contentPadding,
    hasMasklayer,
    masklayerCanClose,
    title,
    content,
    hasConfirmButton,
    confirmButtonText,
    confirmButtonType,
    closeCallback,
    confirmCallback,
  });
};

/**
 * 底部模态框
 * @param {Object} [params = {}]
 * @param {Element} [params.target] 模态挂载目标元素
 * @param {boolean} [params.hasMasklayer] 是否显示遮罩层
 * @param {boolean} [params.masklayerCanClose] 是否允许点击遮罩层关闭模态框
 * @param {string | Element} [params.title] 模态框标题
 * @param {string | Element} [params.content] 模态框消息内容
 * @param {boolean} [params.hasConfirmButton] 是否拥有确认操作按钮
 * @param {string} [params.confirmButtonText] 确认按钮文本
 * @param {'normal' | 'danger'} [params.confirmButtonType] 确认按钮类型
 * @param {Function} [params.closeCallback ] 关闭按钮回调函数
 * @param {Function} [params.confirmCallback ] 确认按钮回调函数
 * @description 关于默认值，可以查看方法参数的默认设置
 */
const bottom = ({
  target,
  contentWidth,
  contentHeight,
  contentPadding,
  hasMasklayer,
  masklayerCanClose,
  title,
  content,
  hasConfirmButton,
  confirmButtonText,
  confirmButtonType,
  closeCallback,
  confirmCallback,
} = {}) => {
  // 创建类型为底部出现的模态框
  createModal({
    modalType: 'bottom',
    target,
    contentWidth,
    contentHeight,
    contentPadding,
    hasMasklayer,
    masklayerCanClose,
    title,
    content,
    hasConfirmButton,
    confirmButtonText,
    confirmButtonType,
    closeCallback,
    confirmCallback,
  });
};

/**
 * 创建模态框核心函数
 * @param {Object} [params = {}]
 * @param {string} [params.modalType] 模态框类型
 * @param {Element} [params.target] 模态挂载目标元素
 * @param {boolean} [params.hasMasklayer] 是否显示遮罩层
 * @param {boolean} [params.masklayerCanClose] 是否允许点击遮罩层关闭模态框
 * @param {string | Element} [params.title] 模态框标题
 * @param {string | Element} [params.content] 模态框消息内容
 * @param {boolean} [params.hasConfirmButton] 是否拥有确认操作按钮
 * @param {string} [params.confirmButtonText] 确认按钮文本
 * @param {'normal' | 'danger'} [params.confirmButtonType] 确认按钮类型
 * @param {Function} [params.closeCallback ] 关闭按钮回调函数
 * @param {Function} [params.confirmCallback ] 确认按钮回调函数
 */
function createModal({
  modalType = 'normal',
  target = document.body,
  contentWidth = '',
  contentHeight = '',
  contentPadding = '',
  hasMasklayer = true,
  masklayerCanClose = true,
  title = '',
  content,
  hasConfirmButton = false,
  confirmButtonText = '确定',
  confirmButtonType = 'normal',
  closeCallback = () => {},
  confirmCallback = () => {},
} = {}) {
  try {
    // 必选项检查 - 模态框内容
    if (!content) {
      throw new URIError(
        '参数配置项里的 "content" 为必选项，请参看 modal.js 模块插件的参数描述。'
      );
    }
  } catch (err) {
    throw new Error('"content" 字段为必选项，请检查方法调用时的参数配置！');
  }

  // 创建模态框主体
  const container = document.createElement('div');
  container.className = 'modal';

  // 创建遮罩层
  const masklayer = document.createElement('div');
  masklayer.className = 'modal-masklayer';

  // 如果点击遮罩层允许关闭模态框
  if (masklayerCanClose) {
    // 点击遮罩层关闭模态框
    masklayer.onclick = () => {
      closeModal(container, masklayer, modalBox, 360, closeCallback);
    };
  }

  // 创建模态框主体
  const modalBox = document.createElement('div');
  // 居中模态框
  if (modalType === 'normal') {
    modalBox.className = 'modal-normal';
  }
  // 底部模态框
  else if (modalType === 'bottom') {
    modalBox.className = 'modal-bottom';
  }
  // 默认为居中模态框
  else {
    modalBox.className = 'modal-normal';
  }

  // 创建标题
  let modalTitle = '';
  if (title !== '') {
    modalTitle = document.createElement('div');
    modalTitle.className = 'modal-title';
    // 如果是一个 Element 元素
    if (title instanceof Element) {
      modalTitle.append(title);
    } else {
      const titleContent = document.createElement('span');
      titleContent.innerHTML = title;
      modalTitle.append(titleContent);
    }
  }

  // 创建内容
  const modalContent = document.createElement('div');
  modalContent.className = 'modal-content';

  // 自定义样式设置
  contentWidth !== '' ? (modalContent.style.width = contentWidth) : null;
  contentHeight !== '' ? (modalContent.style.height = contentHeight) : null;
  contentPadding !== '' ? (modalContent.style.padding = contentPadding) : null;

  // 如果是一个 Element 元素
  if (content instanceof Element) {
    modalContent.append(content);
  } else {
    modalContent.innerHTML = content;
  }

  // 创建操作栏
  const operations = document.createElement('div');
  operations.className = 'modal-operations';

  // 创建操作类型 - 关闭模态框
  const btnClose = document.createElement('div');
  btnClose.className = 'operation-item modal-close';
  btnClose.textContent = '关闭';

  // 关闭按钮事件
  btnClose.onclick = () => {
    closeModal(container, masklayer, modalBox, 360, closeCallback);
  };

  operations.append(btnClose);
  // 如果拥有确认按钮或确认按钮文本不为空
  if (hasConfirmButton || confirmButtonText !== '确定') {
    const btnConfirm = document.createElement('div');
    btnConfirm.className = `operation-item modal-confirm ${confirmButtonType}`;
    btnConfirm.textContent = confirmButtonText;

    // 确认按钮事件
    btnConfirm.onclick = function () {
      closeModal(container, masklayer, modalBox, 260, confirmCallback);
    };

    operations.append(btnConfirm);
  }

  // 组合 DOM
  modalBox.append(modalTitle, modalContent, operations);
  hasMasklayer && container.append(masklayer);
  container.append(modalBox);
  target.append(container);
}

/**
 * 关闭底部模态框
 * @param {Element} container 模态框主容器
 * @param {Element} masklayer 遮罩层
 * @param {Element} bottomModal 底部模态框
 * @param {Number} timeout 延时移除模态框主容器
 * @param {Function} callback 模态框关闭后的回调处理函数
 */
function closeModal(container, masklayer, bottomModal, timeout, callback) {
  // 执行各元素关闭动画
  masklayer.classList.add('close-animation');
  bottomModal.classList.add('close-modal');

  // 等待 CSS 动画完成，移除模态框
  setTimeout(() => {
    container.remove();
  }, timeout);

  // 执行关闭回调函数
  callback();
}

// modal.normal 解构引用
export const modalNormal = normal;

// modal.bottom 解构引用
export const modalBottom = bottom;

// 模块导出对象
const modal = {
  normal,
  bottom,
};

export default modal;
